package com.liry.custommvc.handler;

import com.liry.custommvc.HandlerMapping;
import com.liry.custommvc.HttpRequestHandler;
import com.liry.custommvc.InitMvc;
import com.liry.custommvc.annotation.Controller;
import com.liry.custommvc.annotation.GetMapping;
import com.liry.custommvc.annotation.PostMapping;
import com.liry.custommvc.annotation.RequestMapping;
import com.liry.custommvc.annotation.RequestParam;
import com.liry.custommvc.annotation.ResponseBody;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
 * @author ALI
 * @since 2022/10/5
 */
@Component
public class UrlHandlerMapping implements HandlerMapping, BeanPostProcessor {

    private Map<String, HttpRequestHandler> CACHE = new HashMap<>();

    public static void main(String[] args) {
        String s = "/";
        System.out.println(new UrlHandlerMapping().removePreSpe(s));
    }

    @Override
    public HttpRequestHandler getHandler(HttpServletRequest request) {
        return CACHE.get(request.getRequestURI());
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> aClass = bean.getClass();
        String url = "";
        RequestMapping requestMappingAnnotation = aClass.getAnnotation(RequestMapping.class);
        if (requestMappingAnnotation == null) {
            Controller controllerAnnotation = aClass.getAnnotation(Controller.class);
            if (controllerAnnotation == null) {
                return bean;
            }
            url = controllerAnnotation.value();
        } else {
            url = requestMappingAnnotation.value();
        }
        if (!StringUtils.hasText(url)) {
            url = "/";
        }
        url = InitMvc.context_path + removePreSpe(url);
        parseHandler(url, aClass, beanName);
        return bean;
    }

    private void parseHandler(String rootPath, Class<?> aClass, String beanName) {

        if (!rootPath.endsWith("/")) {
            rootPath += "/";
        }
        boolean returnView = aClass.getAnnotation(ResponseBody.class) != null;
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            HttpRequestHandler result = new HttpRequestHandler();

            RequestMapping annotation = method.getAnnotation(RequestMapping.class);
            GetMapping getMapping = method.getAnnotation(GetMapping.class);
            PostMapping postMapping = method.getAnnotation(PostMapping.class);
            if (annotation != null) {
                result.setUrl(rootPath + removePreSpe(annotation.value()));
            } else if (getMapping != null) {
                result.setUrl(rootPath + removePreSpe(getMapping.value()));
            } else if (postMapping != null) {
                result.setUrl(rootPath + removePreSpe(postMapping.value()));
            }
            if (!StringUtils.hasText(result.getUrl())) {
                continue;
            }
            Parameter[] parameters = method.getParameters();
            if (parameters != null) {
                List<String> paramNameList = new ArrayList<>();
                for (Parameter parameter : parameters) {
                    // todo 反射获取不了参数名称
                    RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
                    if (requestParam != null) {
                        String paramName = requestParam.value();
                        if (StringUtils.hasText(paramName)) {
                            paramNameList.add(paramName);
                        }
                    } else {
                        paramNameList.add(parameter.getName());
                    }
                }
                result.setParamNameList(paramNameList);
            }
            result.setMethod(method);
            result.setObj(aClass);
            if (returnView) {
                result.setReturnView(returnView);
            } else {
                if (method.getAnnotation(ResponseBody.class) != null) {
                    result.setReturnView(true);
                }
            }
            result.setBeanName(beanName);
            HttpRequestHandler httpRequestHandler = CACHE.get(result.getUrl());
            if (httpRequestHandler != null) {
                throw new RuntimeException("url:" + result.getUrl() + " 已经存在，错误类：" + aClass.getName());
            }
            CACHE.put(result.getUrl(), result);
        }
    }

    private String removePreSpe(String path) {
        if (path.startsWith("/")) {
            return path.substring(1);
        }
        return path;
    }
}
